
#ifndef DBPARITION_H_
#define DBPARITION_H_

#include <string>
#include <map>
#include <set>
#include <vector>
#include "status.hxx"

class DataStoreImpl;
class DataSegmentManager;
class StaticIndexArray;
class LogManager;
class CompactOption;
class DataSegment;
class CompactIndexItem;
class Dbt;

/**
 * DbPartition manage an index and a bunch of datasegments 
 */ 
class DbPartition {

private:
	std::string m_partitionName;
	std::string m_partitionPath;
	DataStoreImpl* m_ds;
    LogManager* m_logmgr; 

	DataSegmentManager* m_segmentMgr;
	StaticIndexArray* m_indexarray;

    //TODO: improve concurrency for writing by using multiple locks across index
	pthread_mutex_t m_mutex;//a lock for put/del operations 
    
    //for debug only
    uint64_t m_good;

public:
	DbPartition(DataStoreImpl& ds, LogManager& logMgm, const std::string& partitionName);
	~DbPartition();
		
	//load all of segments in the partition dir
	DbStatus init();

    //flush index and datasegments
    DbStatus flush();

    //flush datasegments
    DbStatus flushSegments();

    //flush index
    DbStatus flushIndexArray();

	DbStatus get(Dbt& key, Dbt& value);
	DbStatus put(Dbt& key, Dbt& value);	
    DbStatus del(Dbt& key);

    //used by recovery only
    DbStatus get(uint16_t segID,
                 uint32_t offset,
                 uint32_t dataSize,
                 std::string& data);

    DbStatus put(uint16_t segID, 
                 uint32_t offset, 
                 const std::string& data, 
                 uint32_t loadSize, 
                 uint32_t index, 
                 uint64_t addrvalue, 
                 uint64_t scn);

	DbStatus setLoadSize(uint16_t segID, uint32_t loadSize);
    std::string getPartitionName() { return m_partitionName; }
    std::string getPartitionPath() { return m_partitionPath; }

    //return the index in the index array
	uint32_t getIndex(Dbt& key);
    DbStatus getAddr(uint32_t index, uint64_t& addr);

    void getWaterMarks(uint64_t& lwm, uint64_t& hwm);

    //do compaction
    DbStatus compact(CompactOption& option);
    
    //switch index update for sync
    void switchEntries();

private:
    //the function is used by put and del
    DbStatus putInternal(Dbt& key,Dbt& value, bool deletion);

    std::map<uint16_t, std::vector<CompactIndexItem> >
        getCompactIndexItemMap(std::set<uint16_t>& segIDList, CompactOption& option);

    DbStatus compactInternal(CompactOption& option, uint16_t segID, std::vector<CompactIndexItem>& vCompactItem);
    DbStatus putForCompact(DataSegment* seg, CompactIndexItem& item); 
};


#endif
